import { GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader'
import { Capsule } from 'three/examples/jsm/math/Capsule'
import * as THREE from 'three'
import { destroy } from '@/utils'

let renderer, camera, scene, animationID;
let clock;
let playerOnFloor = false
let keyStates = {}

let player = {
  geometry: new Capsule(new THREE.Vector3(0, 0.35, 0), new THREE.Vector3(0, 1, 0), 0.35),
  velocity: new THREE.Vector3(),
  direction: new THREE.Vector3()
}

export default function init(container) {
  // renderer
  renderer = new THREE.WebGLRenderer({ antialias: true })  // antialias:true 开启抗锯齿
  // 设置设备像素比。通常用于HiDPI设备防止模糊输出canvas
  renderer.setPixelRatio(window.devicePixelRatio)
  // 设置渲染的宽高 
  renderer.setSize(window.innerWidth, window.innerHeight)
  // 默认为 false. 如果设置了该参数，则启用在场景中的阴影贴图
  renderer.shadowMap.enable = true
  // 阴影贴图类型定义
  renderer.shadowMap.type = THREE.BasicShadowMap;
  renderer.outputEncoding = THREE.sRGBEncoding;
  renderer.toneMapping = THREE.ACESFilmicToneMapping;
  container.appendChild(renderer.domElement);

  // camera
  camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000)
  camera.position.set(0, 0, 0)
  camera.rotation.order = 'YXZ'

  // scene
  scene = new THREE.Scene()
  scene.background = new THREE.Color(0x88ccee)
  // scene.fog = new THREE.Fog(0x88ccee, 0, 50)
  scene.add(new THREE.GridHelper(10))

  // light
  // 半球形光源(HemisphereLight)
  // 光源直接放置于场景之上，光照颜色从天空光线颜色颜色渐变到地面光线颜色。
  // 半球光不能投射阴影。
  const fillLight1 = new THREE.HemisphereLight(0x4488bb, 0x002244, 0.5);
  fillLight1.position.set(2, 1, 1);
  scene.add(fillLight1);

  // 平行光(DirectionalLight)
  // 平行光是沿着特定方向发射的光。
  const directionalLight = new THREE.DirectionalLight(0xffffff, 0.8);
  directionalLight.position.set(- 5, 25, - 1);
  // 如果设置为 true 该平行光会产生动态阴影
  directionalLight.castShadow = true;
  directionalLight.shadow.camera.near = 0.01;
  directionalLight.shadow.camera.far = 500;
  directionalLight.shadow.camera.right = 30;
  directionalLight.shadow.camera.left = - 30;
  directionalLight.shadow.camera.top = 30;
  directionalLight.shadow.camera.bottom = - 30;
  directionalLight.shadow.mapSize.width = 1024;
  directionalLight.shadow.mapSize.height = 1024;
  directionalLight.shadow.radius = 4;
  directionalLight.shadow.bias = - 0.00006;
  scene.add(directionalLight);

  // clock 
  clock = new THREE.Clock()

  // 监听事件移到了vue文件
  // window.addEventListener("resize", onResize)

  loadModel()
}
export const onResize = () => {
  camera.aspect = window.innerWidth / window.innerHeight
  camera.updateProjectionMatrix()
  renderer.setSize(window.innerWidth, window.innerHeight)
}

const loadModel = () => {
  const loader = new GLTFLoader()
  loader.load('./src/pages/building/building102.gltf', gltf => {
    scene.add(gltf.scene)

    gltf.scene.traverse(child => {

      if (child.isMesh) {
        // 阴影效果
        child.castShadow = true;
        child.receiveShadow = true;
      }

    });
  })

  animate()
}

// 渲染
const animate = () => {
  // 时间片段
  const deltaTime = Math.min(0.05, clock.getDelta())
  // 在控制之后，需要更新player的位置
  handleControls(deltaTime)
  updatePlayer(deltaTime)
  renderer.render(scene, camera)
  console.log('building')

  animationID = requestAnimationFrame(animate)
}
const handleControls = (deltaTime) => {
  const speedDelta = deltaTime * 150;

  if (keyStates['KeyW']) {
    // 摁下W，改变水平方向的向量， multiplyScalar 乘积
    player.velocity.add(getForwardVector().multiplyScalar(speedDelta));

  }

  if (keyStates['KeyS']) {

    player.velocity.add(getForwardVector().multiplyScalar(- speedDelta));

  }

  if (keyStates['KeyA']) {

    player.velocity.add(getSideVector().multiplyScalar(- speedDelta));

  }

  if (keyStates['KeyD']) {

    player.velocity.add(getSideVector().multiplyScalar(speedDelta));

  }

  if (playerOnFloor) {

    if (keyStates['Space']) {

      player.velocity.y = 15;

    }

  }
}
const updatePlayer = (deltaTime) => {

  let damping = Math.exp(- 4 * deltaTime) - 1;

  player.velocity.addScaledVector(player.velocity, damping);

  const deltaPosition = player.velocity.clone().multiplyScalar(deltaTime);
  player.geometry.translate(deltaPosition);

  camera.position.copy(player.geometry.end);

}
// 获得前进方向向量
const getForwardVector = ()  => {
  camera.getWorldDirection(player.direction);
  player.direction.y = 0;
  // 转化为单位向量
  player.direction.normalize();

  return player.direction;
}
// 获得左右方向向量
const getSideVector = () => {
  // Camera.getWorldDirection ( target : Vector3 ) : Vector3 调用该函数的结果将赋值给该Vector3对象。
  camera.getWorldDirection(player.direction);
  player.direction.y = 0;

  // 将该向量转换为单位向量（unit vector）， 也就是说，将该向量的方向设置为和原向量相同，但是其长度（length）为1。
  player.direction.normalize();
  player.direction.cross(camera.up);

  return player.direction;
}

// 监听事件移到了vue文件
// document.addEventListener('mousedown', onMousedown)
// document.addEventListener('mousemove', onMousemove)
// document.addEventListener('keydown', onKeydown)
// document.addEventListener('keyup', onKeyup)

export const onMousedown = () => {
  document.body.requestPointerLock()
}

export const onMousemove = (e) => {
  // 当鼠标在锁定状态时
  if (document.pointerLockElement === document.body) {
    camera.rotation.y -= e.movementX / 500
    camera.rotation.x -= e.movementY / 500
  }
}

export const onKeydown = (e) => {
  keyStates[e.code] = true
}

export const onKeyup = (e) => {
  keyStates[e.code] = false
}

/**
 * 清除上下文
 */
export const destroyContext = () => {
  destroy(scene, renderer, animationID)
}
